// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
mod http;
use http::commands::*;
use mcp_client::client::McpClientTrait;
use std::collections::{HashMap, HashSet};
use std::sync::{Arc, Mutex};
use tauri::Manager;
use tokio::sync::Mutex as TokioMutex;
mod extension;
use extension::{add_extension, list_extensions, remove_extension};

#[cfg(feature = "cookies")]
const COOKIES_FILENAME: &str = ".cookies";

type McpClientBox = Arc<TokioMutex<Box<dyn McpClientTrait>>>;

pub(crate) struct AppState {
    #[cfg(feature = "cookies")]
    cookies_jar: Arc<crate::http::reqwest_cookie_store::CookieStoreMutex>,

    clients: HashMap<String, McpClientBox>,
    instructions: HashMap<String, String>,
    resource_capable_extensions: HashSet<String>,
}

#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}! You've been greeted from Rust!", name)
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_opener::init())
        .setup(|app| {
            #[cfg(feature = "cookies")]
            let cookies_jar = {
                use crate::http::reqwest_cookie_store::*;
                use std::fs::File;
                use std::io::BufReader;

                let cache_dir = app.path().app_cache_dir()?;
                std::fs::create_dir_all(&cache_dir)?;

                let path = cache_dir.join(COOKIES_FILENAME);
                let file = File::options()
                    .create(true)
                    .append(true)
                    .read(true)
                    .open(&path)?;

                let reader = BufReader::new(file);
                CookieStoreMutex::load(path.clone(), reader).unwrap_or_else(|_e| {
                    #[cfg(feature = "tracing")]
                    tracing::warn!(
                        "failed to load cookie store: {_e}, falling back to empty store"
                    );
                    CookieStoreMutex::new(path, Default::default())
                })
            };
            let state = AppState {
                #[cfg(feature = "cookies")]
                cookies_jar: Arc::new(cookies_jar),

                clients: HashMap::new(),
                instructions: HashMap::new(),
                resource_capable_extensions: HashSet::new(),
            };

            app.manage(Mutex::new(state));

            Ok(())
        })
        // .on_event(|app, event| {
        //     #[cfg(feature = "cookies")]
        //     if let tauri::RunEvent::Exit = event {
        //         let state = app.state::<Http>();
        //
        //         match state.cookies_jar.request_save() {
        //             Ok(rx) => {
        //                 let _ = rx.recv();
        //             }
        //             Err(_e) => {
        //                 #[cfg(feature = "tracing")]
        //                 tracing::error!("failed to save cookie jar: {_e}");
        //             }
        //         }
        //     }
        // })
        .invoke_handler(tauri::generate_handler![
            greet,
            fetch,
            fetch_cancel,
            fetch_send,
            fetch_read_body,
            add_extension,
            remove_extension,
            list_extensions,
        ])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
